package com.timedomain.him.remake.ui.common;

import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;

import com.timedomain.him.remake.R;
import com.timedomain.him.remake.core.ChannelCreator;
import com.timedomain.him.remake.core.PhoneCall;
import com.timedomain.him.remake.core.SimplePlayer;
import com.timedomain.him.remake.service.PlayerService;
import com.timedomain.him.remake.utils.BaseActivity;
import com.timedomain.him.remake.utils.HLog;
import com.timedomain.him.remake.utils.TimeUtils;
import com.timedomain.him.remake.views.DarkWaveformView;
import com.timedomain.him.remake.views.WaveformView;

import org.jetbrains.annotations.Nullable;

public class CallingActivity extends BaseActivity implements SensorEventListener, AudioManager.OnAudioFocusChangeListener {

    private static final String ExtraAudioPath ="audiopath";
    private static final String ExtraIsMorningCall ="morning";

    public static void startNewCall(Context ctx,String audioPath,boolean isMorningCall){
        Intent intent = new Intent(ctx,CallingActivity.class);
        if(isMorningCall){
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            PlayerService.StopPlayerService(ctx);
        }
        intent.putExtra(ExtraAudioPath,audioPath);
        intent.putExtra(ExtraIsMorningCall,isMorningCall);
        ctx.startActivity(intent);
    }

    private boolean isMorningCall;
    private String audioPath;

    SimplePlayer ringtone;

    private boolean accepted = false;

    TextView txtBeforeCalling = null;
    TextView txtInCalling = null;
    DarkWaveformView waveformView = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|               //这个在锁屏状态下
                        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                        | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.activity_calling);
        txtBeforeCalling = findViewById(R.id.txtBeforeCalling);
        txtInCalling = findViewById(R.id.txtCallingTimer);
        waveformView = findViewById(R.id.callingWaveform);
        waveformView.DarkMode = true;
        this.isMorningCall = getIntent().getBooleanExtra(ExtraIsMorningCall,false);
        this.audioPath = getIntent().getStringExtra(ExtraAudioPath);

        if(isMorningCall){
            int randint = (int)(Math.random() * 10);
            if(randint>9){randint = 9;}
            ringtone = new SimplePlayer(ChannelCreator.FromAsset(getAssets(),"audio/ringtones/"+randint+".ogg"));
        }
        else{
            ringtone = new SimplePlayer(ChannelCreator.FromAsset(getAssets(),"audio/util/defaultcall.ogg"));
        }
        ringtone.setLooping(true);
        ringtone.start();

        setTimerEnabled(true);
        setTimerInterval(1000);
    }

    private Object audioFocusIndicator = null;


    public void endCall(View view) {

        HLog.d("CallingActivityFinish","finish because of EndCall pressed");
        finish();
    }

    // 有些🔈↓↑系统会再按接通之后触发一次返回键，不知道是为什么，那么就搞一个多按几次才能退出的操作
    // 主动出击！
    private long lastPressedTime = -1;

    @Override
    public void onBackPressed() {
        if(System.currentTimeMillis() - lastPressedTime > 1000){
            showToast("再按一次挂断");
            lastPressedTime = System.currentTimeMillis();
            return;
        }
        HLog.d("CallingActivityFinish","End call by pressing back button twice.");
        super.onBackPressed();
    }

    public void startCall(View view) {
        ringtone.stop();
        Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
        vibrator.cancel();
        accepted = true;
        findViewById(R.id.panelBeforeCall).setVisibility(View.GONE);
        findViewById(R.id.panelInCalling).setVisibility(View.VISIBLE);
        findViewById(R.id.callButtonContainer).setVisibility(View.GONE);
        findViewById(R.id.handsFreeContainer).setVisibility(View.VISIBLE);

        ImageButton btnHandsFree = findViewById(R.id.btnHandsFree);
        TextView lblHandsfree = findViewById(R.id.lblHandsFree);

        if(checkIsWired()){
            btnHandsFree.setEnabled(false);
            btnHandsFree.setBackgroundResource(R.drawable.headset);
            lblHandsfree.setText("已连接耳机");
        }
        else{

            AudioManager audioManager = (AudioManager)getSystemService(AUDIO_SERVICE);

            beforeVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            audioManager.setSpeakerphoneOn(false);
            audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) * 90 / 100,AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
        }
        isHeadset = checkIsWired();
        SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

        proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

        PowerManager mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        screenOffWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
                "himremake:calling");
        if(proximitySensor != null && !isHeadset){
            sensorManager.registerListener(this,proximitySensor,300000);

        }
        AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            AudioFocusRequest audioFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
                    .setAudioAttributes(new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).setUsage(AudioAttributes.USAGE_MEDIA).build())
                    .setOnAudioFocusChangeListener(this)
                    .setFocusGain(AudioManager.AUDIOFOCUS_GAIN)
                    .build();

            audioFocusIndicator = audioFocusRequest;
            audioManager.requestAudioFocus(audioFocusRequest);

        }
        else{

            audioManager.requestAudioFocus(this,AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN);

        }
        PlayerService.StartPlayerService(CallingActivity.this,new PhoneCall(ChannelCreator.FromFile(CallingActivity.this,audioPath)));

        callBeginTime = System.currentTimeMillis();
        setTimerInterval(50);
    }

    private int beforeVolume = 0;

    @Override
    protected void onResume() {
        super.onResume();
        if(accepted && proximitySensor != null && !isHeadset){
            SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            sensorManager.registerListener(this,proximitySensor,300000);
        }
        if(!accepted){
            Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
            if(vibrator.hasVibrator()){
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {

                    VibrationEffect vibrationEffect = null;
                    vibrationEffect = VibrationEffect.createWaveform(new long[]{500,500},0);

                    if (android.os.Build.VERSION.SDK_INT >= 29){
                        AudioAttributes audioAttributes =
                                new AudioAttributes.Builder()
                                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                                .setUsage(AudioAttributes.USAGE_ALARM).build();
                        vibrator.vibrate(vibrationEffect,audioAttributes);
                    }
                    else{

                        vibrator.vibrate(vibrationEffect);
                    }

                }
                else{
                    vibrator.vibrate(new long[]{500,500},0);
                }
            }
            else{
                HLog.e("CallActivity", "onResume: Phone has no vibrator");
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if(accepted && proximitySensor != null && !isHeadset){
            SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            sensorManager.unregisterListener(this);
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.values[0] < 0.0001f) {
            if (!screenOffWakeLock.isHeld())
                screenOffWakeLock.acquire();

        } else {
            if (screenOffWakeLock.isHeld())
                screenOffWakeLock.release();
        }
    }


    int dotCount = 0;
    long callBeginTime = -1;

    private int loopedTime = 0;

    @Override
    protected void onTimer() {
        if(!accepted){
            switch (dotCount){
                case 0:
                    txtBeforeCalling.setText(getString(R.string.abcInviteCalling)+".");
                    break;
                case 1:
                    txtBeforeCalling.setText(getString(R.string.abcInviteCalling)+"..");
                    break;
                case 2:
                    txtBeforeCalling.setText(getString(R.string.abcInviteCalling)+"...");
                    break;
            }
            dotCount++;
            if(dotCount > 2){dotCount = 0;}
            loopedTime ++;
            if(loopedTime > 300){
                HLog.d("CallingActivityFinish","Timeout before accept");
                finish();
            }
        }
        else{
            txtInCalling.setText(getString(R.string.abcInCalling)+ TimeUtils.msToTimeStr(System.currentTimeMillis() - callBeginTime));
            if(PlayerService.player != null){
                waveformView.Amplitude = PlayerService.player.getPeak();
            }
            else{
                waveformView.Amplitude = 0;
            }
            if(PlayerService.player == null || PlayerService.player.isStopped()){
                setTimerEnabled(false);
                txtInCalling.setText("通话结束");
                HLog.d("CallingActivityFinish","Calling end");
                setTimeout(this::finish,1000);
            }
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do Nothing
    }

    Sensor proximitySensor = null;
    PowerManager.WakeLock screenOffWakeLock = null;

    boolean isHandsFree = false;

    public void toggleHandsFree(View view) {
        if(isHandsFree){
            AudioManager audioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
            audioManager.setSpeakerphoneOn(false);
            audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
            view.setBackgroundResource(R.drawable.hf2);
            isHandsFree = false;
        }
        else{
            AudioManager audioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
            audioManager.setSpeakerphoneOn(true);
            audioManager.setMode(AudioManager.MODE_NORMAL);
            view.setBackgroundResource(R.drawable.hf1);
            isHandsFree = true;
        }
    }

    private boolean isHeadset = false;


    private boolean checkIsWired() {
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
            for (AudioDeviceInfo device : devices) {
                int deviceType = device.getType();
                if (deviceType == AudioDeviceInfo.TYPE_WIRED_HEADSET
                        || deviceType == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
                        || deviceType == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP
                        || deviceType == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
                    return true;
                }
            }
        } else {
            return audioManager.isWiredHeadsetOn() || audioManager.isBluetoothScoOn() || audioManager.isBluetoothA2dpOn();
        }
        return false;
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        setTimerEnabled(false);
        if(accepted){
            PlayerService.StopPlayerService(this);
        }
        if(screenOffWakeLock!=null && screenOffWakeLock.isHeld()){

            screenOffWakeLock.release();
        }




        SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensorManager.unregisterListener(this);
        AudioManager audioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
        audioManager.setSpeakerphoneOn(false);
        audioManager.setMode(AudioManager.MODE_NORMAL);
        if(!isHeadset && accepted){
            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,beforeVolume,AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if(audioFocusIndicator != null) {
                try {
                    audioManager.abandonAudioFocusRequest((AudioFocusRequest) audioFocusIndicator);
                }catch (Exception ex){}
            }
        }
        else{
            try {
                audioManager.abandonAudioFocus(this);
            }catch (Exception ex){}
        }
        if(ringtone != null){

            ringtone.close();
        }
        Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
        vibrator.cancel();
    }

    boolean hasStartedRingtong = false;

    @Override
    public void onAudioFocusChange(int focusChange) {
        if(focusChange == AudioManager.AUDIOFOCUS_GAIN){
            if(!hasStartedRingtong){
                hasStartedRingtong = true;

            }
        }
        if(focusChange < 0){

            HLog.d("CallingActivityFinish","Audio focus lost");
            finish();
        }
    }
}
